/*
 * Wave - Generates a line of creeps following a *specific* path with
 * a certain amount of health.
 *
 * Copyright 2008 James W. Hofmann
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

package rules;

import lib3f.IntPoint;

class Wave
{

	inline public static var timebetweencreeps = 31;
	inline public static var basenumcreeps = 10;

	public var num : Int;
	public var path : Array<IntPoint>;
	public var timer : Int;
	public var creepsleft : Int;
	public var corner : Int;
	public var count : Int;

	public static function nextwave()
	{
		RulesAPI.g.wavenum+=1;
		var newwave = new Wave();
		RulesAPI.g.wavehash.set(RulesAPI.g.wavenum, newwave);		
	}

	public function new()
	{
		var game = RulesAPI.g;
		this.num = game.wavenum;

		path = new Array();

		// we need only the outer shore; the inner shore has
		// some unreachable areas
		// however an inner shore repr might be useful later, so keep
		// it around

		creepsleft = basenumcreeps;
		timer = 1;
		count = 0;
		
		var outershorechoice = 
			game.lcg.randInt(game.shorelineouter.length-1);
		var outerpoint = game.shorelineouter[outershorechoice];

		var innerchoices : Array<GameTile> = new Array();
		for (n in game.m.tiles[outerpoint.x][outerpoint.y]
			.neighbors)
			if (n.terrain!=GameTile.ter_space)
				innerchoices.push(n);
		
		var innerchoice = game.lcg.randInt(innerchoices.length-1);
		var innerpoint = new IntPoint(innerchoices[innerchoice].x,
									  innerchoices[innerchoice].y);

		this.path = pathgen(outerpoint, innerpoint, 
							game.wavecornercycle);

		corner = game.wavecornercycle;		
		game.wavecornercycle+=1;		
		if (game.wavecornercycle>3)
			game.wavecornercycle = 0;

		GameResponse.addcomposition(
			new GameResponse(GameResponse.msg_newwave, this));
	}

	public function pathgen(outer : IntPoint, inner : IntPoint,
							corner : Int)
	{
		var result : Array<IntPoint> = new Array();
		
		var cur : Node;
		var start : Node;
		var end : Node;
		
		start = RulesAPI.g.creepspawnshorepaths[corner].nodes
			[GameMap.corners[corner][0]]
			[GameMap.corners[corner][1]];

		end = RulesAPI.g.creepshorebasepath.nodes
			[GameMap.mapxcenter]
			[GameMap.mapycenter];
		
		cur = RulesAPI.g.creepspawnshorepaths[corner].nodes
			[outer.x]
			[outer.y];
		
		while (cur.parent.x!=start.parent.x || 
			   cur.parent.y!=start.parent.y)
		{
			result.push(new IntPoint(cur.parent.x, cur.parent.y));
			var randdir = RulesAPI.g.lcg.randInt
				(cur.directions.length-1);
			cur = cur.directions[randdir];
		}
		result.push(new IntPoint(cur.parent.x, cur.parent.y));
				
		cur = RulesAPI.g.creepshorebasepath.nodes
			[inner.x]
			[inner.y];
		
		while (cur.parent.x!=end.parent.x || 
			   cur.parent.y!=end.parent.y)
		{
			result.insert(0,new IntPoint(cur.parent.x, cur.parent.y));
			var randdir = RulesAPI.g.lcg.randInt
				(cur.directions.length-1);
			cur = cur.directions[randdir];
		}
		result.insert(0,new IntPoint(cur.parent.x, cur.parent.y));

		return result;
	}
	
	public function up()
	{
		// add creeps on a timer

		if (creepsleft>0)
		{
			timer-=1;
			if (timer<=0)
			{
				timer = timebetweencreeps;
				creepsleft -=1;
				count+=1;
				new Creep(corner, this);
			}
		}

		if (count<=0) // decreased by the creeps as they die
			done();
	}
	
	public function done()
	{
		RulesAPI.g.wavehash.remove(this.num);

		GameResponse.addcomposition(
			new GameResponse(GameResponse.msg_waveover, this));
	}

}
